package cn.songtx.iot.controller;

import cn.songtx.iot.pojo.Result;
import cn.songtx.iot.pojo.SysUser;
import cn.songtx.iot.service.ISysUserService;
import cn.songtx.iot.utils.JWTUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.songtx.iot.utils.MD5Utils.getMd5;

@RestController
@RequestMapping("/sysUser")
@RequiredArgsConstructor
public class SysUserController {
    private final ISysUserService userService;

    /**
     * 账户管理:创建账号,增,删,改,登陆
     * phoneNumber在数据库中有唯一性要求,无法重复创建
     * 如重复创建,数据库返回异常值,由统一的故障拦截返回数据,主键自增一次.
     * cn/songtx/iot/config/GlobalExceptionHandler.java
     * 密码的保存用MD5加密
     *
     * @param sysUser 用户对象
     * @return 返回状态
     */
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public Result userSave(@RequestBody SysUser sysUser) {
        if (sysUser.getPhoneNumber() != null && sysUser.getPassword() != null && sysUser.getUserName() != null) {
            // 获得password,MD5加密,返回password
            sysUser.setPassword(getMd5(sysUser.getPassword()));
            sysUser.setCreateTime(LocalDateTime.now());
            boolean saved = userService.save(sysUser);
            return Result.success(saved ? "创建成功" : "创建失败");
        }
        return Result.error("创建账户数据不全");
    }

    /*
     * 账户管理:根据id逻辑删除
     * 删除前判断是否名下有家庭数据
     * */
    @RequestMapping(value = "/deleteById/{id}", method = RequestMethod.DELETE)
    public Result userDelete(@PathVariable("id") Long id) {
        boolean removed = userService.removeById(id);
        return Result.success(removed ? "逻辑删除成功" : "删除失败");
    }

    /**
     * 账户管理:修改密码/显示名
     * 必须要有id不可修改,手机号/密码不能为空
     *
     * @param sysUser POST 用户数据
     * @return 修改状态
     */
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public Result userUpdate(@RequestBody SysUser sysUser) {
        if (sysUser.getId() != null) {
            if (sysUser.getPassword() != null) {                  // 如果修改了password,MD5加密
                sysUser.setPassword(getMd5(sysUser.getPassword()));
            }
            sysUser.setUpdateTime(LocalDateTime.now());           // 更新修改时间
            boolean updateById = userService.updateById(sysUser);
            return Result.success(updateById ? "修改成功" : "修改失败");
        }
        return Result.success("未定义主键");
    }

    /**
     * 查询账户信息
     * 根据id或者手机号
     *
     * @param sysUserId 用户id
     * @return 用户信息, 不返回密码
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public Result userList(String sysUserId, String phoneNumber) {
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 带condition + StringUtils组装条件存在判断的构造方法,空的Long类型不适用,用String接收
        sysUserLambdaQueryWrapper.select(SysUser::getId, SysUser::getPhoneNumber, SysUser::getUserName,
                        SysUser::getLoginTime, SysUser::getLoginTimes, SysUser::getCreateTime, SysUser::getUpdateTime)
                .eq(StringUtils.isNotBlank(sysUserId), SysUser::getId, sysUserId)
                .eq(StringUtils.isNotBlank(phoneNumber), SysUser::getPhoneNumber, phoneNumber);
        return Result.success(userService.getOne(sysUserLambdaQueryWrapper));
    }

    /**
     * 账户管理:登陆用POST请求,更安全
     * 匹配账号密码,通过验证后,返回list长度为1
     * 返回token,其中payload携带id,name
     * 更新登陆次数和登陆时间
     *
     * @param sysUser POST对象
     * @return 返回统一的Result
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Result userLogin(@RequestBody SysUser sysUser) {
        // 获得password,MD5加密,返回password
        sysUser.setPassword(getMd5(sysUser.getPassword()));
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(SysUser::getId, SysUser::getLoginTimes)    // 需要getId和getLoginTimes两个数据
                .eq(SysUser::getPhoneNumber, sysUser.getPhoneNumber())
                .eq(SysUser::getPassword, sysUser.getPassword());
        List<SysUser> list = userService.list(lambdaQueryWrapper);
        Result result = new Result();
        if (list.size() == 1) {
            /*
             * 验证通过后,返回登陆账号的对象,返回数据非必要不发送
             * 更新登陆时间和登陆次数
             * */
            SysUser user = new SysUser();
            user.setId(list.get(0).getId());
            user.setLoginTime(LocalDateTime.now());
            user.setLoginTimes(list.get(0).getLoginTimes() + 1);
            userService.updateById(user);
            /*
             * 通过验证后构造token,并携带数据
             * 携带id,前端Store中持久化
             * */
            Map<String, String> payload = new HashMap<>();
            payload.put("id", list.get(0).getId().toString());               // 携带id
            // 用Utils/JWTUtils中的方法生成token
            String token = JWTUtils.getToken(payload);
            // 生成统一的result对象
            result.setCode(200);
            result.setMsg("登陆成功");
            result.setData(token);
        } else {
            result.setCode(401);
            result.setMsg("登陆失败");
            result.setData("登陆失败");
        }
        return result;
    }
}
